package org.maven.dependencybrowser.controller;
/**********************************************************************
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:

**********************************************************************/
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Exclusion;
import org.apache.maven.model.Model;
import org.maven.dependencybrowser.assembler.Assembler;
import org.maven.dependencybrowser.assembler.AssemblerException;
import org.maven.dependencybrowser.controller.model.DuplicatesListManager;
import org.maven.dependencybrowser.implementations.IProgressMeter;
import org.maven.dependencybrowser.implementations.Repository;
import org.maven.dependencybrowser.model.Artifact;
import org.maven.dependencybrowser.model.ArtifactInitialisationException;
import org.maven.dependencybrowser.model.PomFile;
import org.maven.dependencybrowser.model.LeafDependency;

import java.util.Stack;

public class ArtifactResolver
{

    public static final String ROLE = "org.maven.dependencybrowser.controller.ArtifactResolver";

    private Controller controller;
    private Assembler assembler;
    private DuplicatesListManager duplicatesListManager;
    private Repository repository;

    /**
     * @param dependencyHeirarchyParent -
     * the pom file containing the dependency
     * @param progress
     * @param path
     * @param dependency -
     * the dependency requiring resolution
     * @return the artifact indicated by this dependency information or null if
     *         the artifact has been excluded by the scope filters or exclusions
     * @throws DependencyResolutionException if smth is out of order
     */
    public Artifact resolveArtifact(PomFile dependencyHeirarchyParent, Dependency dependency, IProgressMeter progress, Stack<LeafDependency> path)
            throws DependencyResolutionException
    {
        String groupId = dependency.getGroupId();
        String artifactId = dependency.getArtifactId();
        String version = dependency.getVersion();

        // resolve scope and exclude if scope is not being shown
        String scope = dependency.getScope();
        if (isNullOrEmpty(scope))
        {
            scope = Artifact.DEFAULT_SCOPE;
        }
        if (!controller.includeScope(scope))
        {
            return null;
        }
        if (controller.getResolveExclusions().getValue())
        {
            if (dependencyHeirarchyParent.isExcluded(groupId, artifactId, new Stack<Artifact>()))
            {
                return null;
            }
        }

        // attempt to locate a pom file for this dependency
        try
        {
            Model model = repository.resolveFile(groupId, artifactId, version);
            if (model == null)
            {
                // if a corresponsing pom file does not exist then add the
                // dependancy as a leaf node
                LeafDependency leafDependency = new LeafDependency(dependencyHeirarchyParent, dependency, scope);
                duplicatesListManager.add(leafDependency);
                return leafDependency;
            }
            // if a pom file exists then add as a non-leaf node
            PomFile pomFile = new PomFile(assembler.assemble(model, repository), dependencyHeirarchyParent, scope);
            addPomToDuplicatesList(pomFile);
            if (controller.getResolveExclusions().getValue())
            {
                addExclusions(pomFile, dependency);
            }
            pomFile.resolveDependencies(this, progress, path);
            return pomFile;
        }
        catch (ArtifactInitialisationException e)
        {
            throw new DependencyResolutionException(e);
        }
        catch (AssemblerException e)
        {
            throw new DependencyResolutionException(e);
        }
    }

    public void addPomToDuplicatesList(PomFile pomFile)
    {
        duplicatesListManager.add(pomFile);
    }

    private void addExclusions(Artifact artifact, Dependency dependency)
    {
        for (Object o : dependency.getExclusions())
        {
            Exclusion exclusion = (Exclusion) o;
            artifact.addExclusion(exclusion.getGroupId(), exclusion.getArtifactId());
        }
    }

    private boolean isNullOrEmpty(String value)
    {
        return value == null || value.trim().length() == 0;
    }
}
